import { ChildLimit, Fortune, Gender, HeavenStem, EarthBranch, LunarMonth, SixtyCycleMonth, SixtyCycleYear, SolarTime, SolarTerm, SixtyCycle, Zodiac, Constellation, SolarDay, LunarDay, LunarHour, HideHeavenStemDay, TwentyEightStar, Zone, Beast, LunarYear } from "./bazi-utils";
import { calculateShensha, calculatePillarShensha } from "./shensha";
import { getTenStarShort } from "../constants/ten-star";
import { calculateSimpleWuxingCount } from "./wuxing";

/**
 * 获取地支藏干（本气、中气、余气）
 * @param earthBranch 地支对象
 * @returns 藏干字符串
 */
export function getHiddenStems(earthBranch: EarthBranch): string {
  const hideHeavenStems = earthBranch.getHideHeavenStems();
  return hideHeavenStems.map(hs => hs.getName()).join('');
}

/**
 * 计算空亡
 * @param sixtyCycle 六十甲子对象
 * @returns 空亡地支
 */
export function calculateKongwang(sixtyCycle: SixtyCycle): string {
  const extraBranches = sixtyCycle.getExtraEarthBranches();
  return extraBranches.map(branch => branch.getName()).join('');
}

/**
 * 计算命卦
 * @param birthYear 出生年份
 * @param gender 性别
 * @returns 命卦信息
 */
export function calculateMinggua(birthYear: number, gender: Gender): string {
  // 计算整个年份所有数字之和
  let sum = 0;
  let year = birthYear;
  while (year > 0) {
    sum += year % 10;
    year = Math.floor(year / 10);
  }
  
  // 如果结果大于9，继续相加直到小于等于9
  while (sum > 9) {
    let tempSum = 0;
    let num = sum;
    while (num > 0) {
      tempSum += num % 10;
      num = Math.floor(num / 10);
    }
    sum = tempSum;
  }
  
  let hexagramIndex: number;
  if (gender === Gender.MAN) {
    // 男命：11 - 最终结果
    hexagramIndex = 11 - sum;
    // 特殊处理：如果结果为10，转换为1（坎卦）
    if (hexagramIndex === 10) {
      hexagramIndex = 1;
    }
  } else {
    // 女命：最终结果 + 4，如果大于9则减去9
    hexagramIndex = sum + 4;
    if (hexagramIndex > 9) {
      hexagramIndex -= 9;
    }
    // 特殊处理：如果结果为5，转换为8（艮卦）
    if (hexagramIndex === 5) {
      hexagramIndex = 8;
    }
  }
  
  // 八卦对应表：1坎2坤3震4巽6乾7兑8艮9离（没有5中宫）
  const hexagramMap: Record<number, { name: string; direction: string }> = {
    1: { name: '坎卦', direction: '东四命' },
    2: { name: '坤卦', direction: '西四命' },
    3: { name: '震卦', direction: '东四命' },
    4: { name: '巽卦', direction: '东四命' },
    6: { name: '乾卦', direction: '西四命' },
    7: { name: '兑卦', direction: '西四命' },
    8: { name: '艮卦', direction: '西四命' },
    9: { name: '离卦', direction: '东四命' }
  };
  
  const hexagram = hexagramMap[hexagramIndex];
  return hexagram ? hexagram.name + ' (' + hexagram.direction + ')' : '未知';
}

/**
 * 计算12长生（星运：以日干为基准）
 * @param dayMaster 日干
 * @param earthBranch 地支
 * @returns 12长生名称
 */
export function calculateStarTerrain(dayMaster: HeavenStem, earthBranch: EarthBranch): string {
  try {
    const terrain = dayMaster.getTerrain(earthBranch);
    return terrain.getName();
  } catch (error) {
    return '';
  }
}

/**
 * 计算12长生（自坐：以各柱天干为基准）
 * @param heavenStem 天干
 * @param earthBranch 地支
 * @returns 12长生名称
 */
export function calculateSelfTerrain(heavenStem: HeavenStem, earthBranch: EarthBranch): string {
  try {
    const terrain = heavenStem.getTerrain(earthBranch);
    return terrain.getName();
  } catch (error) {
    return '';
  }
}

/**
 * 计算藏干和副星（藏干对应的十神）
 * @param dayMaster 日干
 * @param hiddenStems 藏干字符串
 * @returns 藏干副星数组（保持本气、中气、余气顺序）
 */
export function calculateHiddenStemsAndSubStars(dayMaster: HeavenStem, hiddenStems: string): Array<{ stem: string; tenStar: string; type: string; wuxing: string }> {
  if (!hiddenStems) return [];
  
  const result: Array<{ stem: string; tenStar: string; type: string; wuxing: string }> = [];
  const types = ['本气', '中气', '余气']; // 按顺序定义
  
  for (let i = 0; i < hiddenStems.length; i++) {
    const stem = hiddenStems[i];
    try {
      const stemObj = HeavenStem.fromName(stem);
      const tenStar = dayMaster.getTenStar(stemObj).getName();
      result.push({
        stem: stem,
        tenStar: tenStar,
        type: types[i] || '其他', // 本气、中气、余气
        wuxing: getWuxing(stem)
      });
    } catch (error) {
      // 忽略错误，继续处理下一个
    }
  }
  return result;
}

/**
 * 获取天干的五行
 */
function getWuxing(stem: string): string {
  const wuxingMap: { [key: string]: string } = {
    '甲': '木', '乙': '木',
    '丙': '火', '丁': '火', 
    '戊': '土', '己': '土',
    '庚': '金', '辛': '金',
    '壬': '水', '癸': '水'
  };
  return wuxingMap[stem] || '';
}

/**
 * 通用计算六十甲子详细信息 - 消除重复代码
 * @param childLimit 命造
 * @param dayMaster 日干
 * @param sixtyCycle 六十甲子对象
 * @param sixtyCycleName 六十甲子名称（可选，用于神煞计算）
 * @returns 详细信息对象
 */
function calculateSixtyCycleInfo(
  childLimit: ChildLimit, 
  dayMaster: HeavenStem, 
  sixtyCycle: SixtyCycle, 
  sixtyCycleName?: string
) {
  const heavenStem = sixtyCycle.getHeavenStem();
  const earthBranch = sixtyCycle.getEarthBranch();
  
  // 计算十神
  const heavenStemTenStar = dayMaster.getTenStar(heavenStem).getName();
  const earthBranchTenStar = dayMaster.getTenStar(earthBranch.getHideHeavenStemMain()).getName();
  
  // 计算神煞
  const shenshas = calculateShensha(childLimit, sixtyCycleName || sixtyCycle.getName());
  
  // 获取藏干信息
  const hiddenStems = getHiddenStems(earthBranch);
  const hiddenStemsAndSubStars = calculateHiddenStemsAndSubStars(dayMaster, hiddenStems);
  
  // 计算12长生
  const starTerrain = calculateStarTerrain(dayMaster, earthBranch);
  const selfTerrain = calculateSelfTerrain(heavenStem, earthBranch);
  
  // 计算空亡
  const kongwang = calculateKongwang(sixtyCycle);
  
  // 获取纳音
  const nayin = sixtyCycle.getSound().getName();
  
  return {
    heavenStemTenStar,
    earthBranchTenStar,
    shenshas,
    hiddenStemsAndSubStars,
    starTerrain,
    selfTerrain,
    kongwang,
    nayin
  };
}

/**
 * 构建十神对象 - 消除重复的 tenStar 对象构建
 * @param heavenStemTenStar 天干十神
 * @param earthBranchTenStar 地支十神
 * @returns 十神对象
 */
function buildTenStarObject(heavenStemTenStar: string, earthBranchTenStar: string) {
  return {
    heavenStem: heavenStemTenStar, // 天干十神
    heavenStemShort: getTenStarShort(heavenStemTenStar), // 天干十神缩写
    earthBranch: earthBranchTenStar, // 地支十神（主藏干）
    earthBranchShort: getTenStarShort(earthBranchTenStar) // 地支十神缩写
  };
}

/**
 * 构建通用结果对象 - 消除重复的结果对象构建
 * @param ganzhi 干支名称
 * @param info 计算信息对象
 * @param extraFields 额外字段
 * @returns 结果对象
 */
function buildCommonResultObject(ganzhi: string, info: any, extraFields: any = {}) {
  return {
    ganzhi,
    tenStar: buildTenStarObject(info.heavenStemTenStar, info.earthBranchTenStar),
    zanggan: info.hiddenStemsAndSubStars, // 藏干副星对象
    xingyun: info.starTerrain, // 星运（12长生）
    zizuo: info.selfTerrain, // 自坐（12长生）
    kongwang: info.kongwang, // 空亡
    nayin: info.nayin, // 纳音
    shenshas: info.shenshas, // 神煞数组
    ...extraFields // 合并额外字段
  };
}

/**
 * 通用错误处理函数 - 统一错误处理模式
 * @param error 错误对象
 * @param context 上下文信息（可选）
 */
function handleError(error: any, context?: string) {
  console.error(context ? `${context} error:` : 'Error:', error);
  throw new Error('网络环境不佳，请稍后尝试');
}

/**
 * 计算特殊柱信息（身宫、命宫、胎元）
 * @param childLimit ChildLimit对象
 * @param dayMaster 日干
 * @param sixtyCycle 六十甲子对象
 * @returns 特殊柱详细信息
 */
export function calculateSpecialPillarInfo(childLimit: ChildLimit, dayMaster: HeavenStem, sixtyCycle: SixtyCycle) {
  try {
    const stem = sixtyCycle.getHeavenStem();
    const branch = sixtyCycle.getEarthBranch();
    
    // 计算详细信息
    const hiddenStems = getHiddenStems(branch);
    const hiddenStemsAndSubStars = calculateHiddenStemsAndSubStars(dayMaster, hiddenStems);
    
    // 计算神煞和空亡
    const shenshas = calculateShensha(childLimit, sixtyCycle.getName());
    const kongwang = calculateKongwang(sixtyCycle);
    
    // 获取纳音
    const nayin = sixtyCycle.getSound().getName();
    
    return {
      stem: stem.getName(),
      branch: branch.getName(),
      ganzhi: sixtyCycle.getName(),
      tenStar: dayMaster.getTenStar(stem).getName(),
      zanggan: hiddenStemsAndSubStars,
      xingyun: calculateStarTerrain(dayMaster, branch),
      zizuo: calculateSelfTerrain(stem, branch),
      kongwang: kongwang,
      nayin: nayin,
      shenshas: shenshas
    };
  } catch (error) {
    console.error('calculateSpecialPillarInfo error:', error);
    return {
      stem: '',
      branch: '',
      ganzhi: '',
      tenStar: '',
      zanggan: [],
      xingyun: '',
      zizuo: '',
      kongwang: '',
      nayin: '',
      shenshas: []
    };
  }
}

/**
 * 获取小运列表
 * @param childLimit ChildLimit对象
 * @returns 小运列表
 */
export function getChildFortuneList(childLimit: ChildLimit) {
  try {
    const result: any = [];
    
    // 从 childLimit 内部获取日干（日元）
    const dayMaster = childLimit.getEightChar().getDay().getHeavenStem();
    
    // 小运的 sixtyCycle 应该取流年列表第一个的 childFortuneSixtyCycle
    const yearList = getFortuneList(childLimit, 0);
    const sixtyCycle = yearList.length > 0 ? yearList[0].childFortuneSixtyCycle : childLimit.getStartFortune().getSixtyCycle().getName();
    
    // 根据 sixtyCycle 创建 SixtyCycle 对象来计算所有结果
    const sixtyCycleObj = SixtyCycle.fromName(sixtyCycle);
    
    // 使用通用方法计算详细信息
    const info = calculateSixtyCycleInfo(childLimit, dayMaster, sixtyCycleObj, sixtyCycle);
    
    // 获取出生年份
    const birthYear = childLimit.getStartTime().getYear();
    const startAge = childLimit.getStartAge();
    const endAge = childLimit.getEndAge();
    
    result.push(buildCommonResultObject(sixtyCycle, info, {
      xiaoyun: true,
      startAge: startAge,
      endAge: endAge,
      startYear: birthYear + startAge - 1, // 开始年份
      endYear: birthYear + endAge - 1, // 结束年份
    }));
    
    return result;
  } catch (error) {
    handleError(error, 'getChildFortuneList');
  }
}

/**
 * 获取大运列表（包含童限）
 * @param childLimit ChildLimit对象
 * @returns 大运列表
 */
export function getDecadeFortuneList(childLimit: ChildLimit) {
  try {
    const result: any = [];
    
    // 从 childLimit 内部获取日干（日元）
    const dayMaster = childLimit.getEightChar().getDay().getHeavenStem();
    
    
    // 童限（小运）
    const childFortuneList = getChildFortuneList(childLimit);
    for (const childFortune of childFortuneList) {
      // 为童限添加流年列表（children）
      const fortuneList = getFortuneList(childLimit, 0);
      result.push({
        ...childFortune,
        children: fortuneList
      });
    }
    
    // 大运
    let decade = childLimit.getStartDecadeFortune();
    for (let i = 0; i < 10; i++) {
      const sixtyCycle = decade.getSixtyCycle();
      
      // 使用通用方法计算详细信息
      const info = calculateSixtyCycleInfo(childLimit, dayMaster, sixtyCycle);
      
      const startYear = decade.getStartSixtyCycleYear().getYear();
      const endYear = decade.getEndSixtyCycleYear().getYear();

      const decadeItem = buildCommonResultObject(sixtyCycle.getName(), info, {
        startAge: decade.getStartAge(),
        endAge: decade.getEndAge(),
        startYear: startYear, // 开始年份
        endYear: endYear, // 结束年份
      });
      
      // 为每个大运添加流年列表（children）
      // decadeIndex 从 1 开始（0 是童限）
      const fortuneList = getFortuneList(childLimit, i + 1);
      decadeItem.children = fortuneList;
      
      result.push(decadeItem);
      decade = decade.next(1);
    }
    
    return result;
  } catch (error) {
    handleError(error, 'getDecadeFortuneList');
  }
}

/**
 * 获取流年列表
 * @param childLimit ChildLimit对象
 * @param decadeIndex 大运索引
 * @returns 流年列表
 */
export function getFortuneList(childLimit: ChildLimit, decadeIndex: number) {
  try {
    const result: any = [];
    
    // 从 childLimit 内部获取日干（日元）
    const dayMaster = childLimit.getEightChar().getDay().getHeavenStem();
    
    // 获取指定大运
    let decade;
    if (decadeIndex === 0) {
      // 童限
      decade = childLimit.getDecadeFortune();
    } else {
      // 正式大运
      decade = childLimit.getStartDecadeFortune();
      for (let i = 1; i < decadeIndex; i++) {
        decade = decade.next(1);
      }
    }
    
    // 获取该大运的流年
    let fortune = decade.getStartFortune();
    if (fortune.getAge() > 0) {
      const sixtyCycle = fortune.getSixtyCycleYear().getSixtyCycle();
      
      // 使用通用方法计算详细信息
      const info = calculateSixtyCycleInfo(childLimit, dayMaster, sixtyCycle);
      
      result.push(buildCommonResultObject(sixtyCycle.getName(), info, {
        year: fortune.getSixtyCycleYear().getYear(),
        childFortuneSixtyCycle: fortune.getSixtyCycle().getName(), // 小运干支
      }));
    }
    
    for (let i = 0; i < 9; i++) {
      fortune = fortune.next(1);
      if (fortune.getAge() > 0) {
        const sixtyCycle = fortune.getSixtyCycleYear().getSixtyCycle();
        
        // 使用通用方法计算详细信息
        const info = calculateSixtyCycleInfo(childLimit, dayMaster, sixtyCycle);
        
        result.push(buildCommonResultObject(sixtyCycle.getName(), info, {
          year: fortune.getSixtyCycleYear().getYear(),
          childFortuneSixtyCycle: fortune.getSixtyCycle().getName(), // 小运干支
        }));
      }
    }
    
    return result;
  } catch (error) {
    handleError(error, 'getFortuneList');
  }
}

/**
 * 获取流月列表
 * @param childLimit ChildLimit对象
 * @param decadeIndex 大运索引
 * @param fortuneIndex 流年索引
 * @returns 流月列表
 */
export function getMonthList(childLimit: ChildLimit, decadeIndex: number, fortuneIndex: number) {
  try {
    const result: any = [];
    
    // 从 childLimit 内部获取日干（日元）
    const dayMaster = childLimit.getEightChar().getDay().getHeavenStem();
    
    // 获取指定大运
    let decade;
    if (decadeIndex === 0) {
      decade = childLimit.getDecadeFortune();
    } else {
      decade = childLimit.getStartDecadeFortune();
      for (let i = 1; i < decadeIndex; i++) {
        decade = decade.next(1);
      }
    }
    
    // 获取指定流年
    let fortune = decade.getStartFortune();
    for (let i = 0; i < fortuneIndex; i++) {
      fortune = fortune.next(1);
    }

    // 我们需要使用流年列表中的实际年份
    const fortuneInfo = getFortuneList(childLimit, decadeIndex);
    const actualDisplayYear = fortuneInfo[fortuneIndex].year; // 这是显示年份
    
    const realYear = SixtyCycleYear.fromYear(actualDisplayYear);
    const months: SixtyCycleMonth[] = realYear.getMonths();
    
    for (let i = 0; i < months.length; i++) {
      const month: SixtyCycleMonth = months[i];
      
      // 直接从月份对象获取第一天，这个第一天就是基于正确节气计算的
      const firstDay = month.getFirstDay();
      const startDate = firstDay.getSolarDay();
      
      // 获取开始节气 - 根据月份索引计算节气索引
      const solarTermIndex = 3 + i * 2; // 立春是索引3，每个月增加2
      const startSolarTerm = SolarTerm.fromIndex(actualDisplayYear, solarTermIndex);
      
      // 获取流月的天干地支用于计算十神
      const monthSixtyCycle = month.getSixtyCycle();
      
      // 使用通用方法计算详细信息
      const info = calculateSixtyCycleInfo(childLimit, dayMaster, monthSixtyCycle);
      
      result.push(buildCommonResultObject(month.getSixtyCycle().getName(), info, {
        monthIndex: i, // 流月序号（从0开始）
        firstDay: firstDay.getSixtyCycle().getName(), // 第一天的干支
        startDate: {
          year: startDate.getYear(),
          month: startDate.getMonth(),
          day: startDate.getDay()
        }, // 开始日期
        startSolarTerm: startSolarTerm.getName(), // 开始节气名称
      }));
    }
    
    return result;
  } catch (error) {
    handleError(error, 'getMonthList');
  }
}

/**
 * 获取流日列表
 * @param childLimit ChildLimit对象
 * @param decadeIndex 大运索引
 * @param fortuneIndex 流年索引
 * @param monthIndex 流月索引
 * @returns 流日列表
 */
export function getDayList(childLimit: ChildLimit, decadeIndex: number, fortuneIndex: number, monthIndex: number) {
  try {
    const result: any = [];
    
    // 从 childLimit 内部获取日干（日元）
    const dayMaster = childLimit.getEightChar().getDay().getHeavenStem();
    
    // 获取指定流月信息
    const monthList = getMonthList(childLimit, decadeIndex, fortuneIndex);
    const selectedMonth = monthList[monthIndex];
    
    // 获取指定年份的干支年对象
    const fortuneInfo = getFortuneList(childLimit, decadeIndex);
    const actualDisplayYear = fortuneInfo[fortuneIndex].year;
    const realYear = SixtyCycleYear.fromYear(actualDisplayYear);
    const months = realYear.getMonths();
    const targetMonth = months[monthIndex];
    
    // 从流月的第一天开始，获取该月的所有日子
    const firstDay = targetMonth.getFirstDay();
    let currentDay = firstDay;
    
    // 计算下一个节气的开始时间作为结束时间
    let nextMonthStartDate;
    if (monthIndex < 11) {
      // 不是最后一个月，用下一个月的开始时间
      const nextMonth = monthList[monthIndex + 1];
      nextMonthStartDate = new Date(nextMonth.startDate.year, nextMonth.startDate.month - 1, nextMonth.startDate.day);
    } else {
      // 最后一个月，用下一年第一个月的开始时间
      const nextYearFirstMonth = SixtyCycleYear.fromYear(actualDisplayYear + 1).getMonths()[0];
      const nextFirstDay = nextYearFirstMonth.getFirstDay().getSolarDay();
      nextMonthStartDate = new Date(nextFirstDay.getYear(), nextFirstDay.getMonth() - 1, nextFirstDay.getDay());
    }
    
    let dayCount = 0;
    while (true) {
      const solarDay = currentDay.getSolarDay();
      const currentDate = new Date(solarDay.getYear(), solarDay.getMonth() - 1, solarDay.getDay());
      
      // 如果到达下个节气时间，停止
      if (currentDate >= nextMonthStartDate) {
        break;
      }
      
      // 获取阴历信息
      const lunarDay = solarDay.getLunarDay();
      
      // 获取流日的天干地支用于计算十神
      const daySixtyCycle = currentDay.getSixtyCycle();
      
      // 使用通用方法计算详细信息
      const info = calculateSixtyCycleInfo(childLimit, dayMaster, daySixtyCycle);
      
      result.push(buildCommonResultObject(currentDay.getSixtyCycle().getName(), info, {
        dayIndex: dayCount, // 流日序号（从0开始）
        date: {
          solar: {
            year: solarDay.getYear(),
            month: solarDay.getMonth(), 
            day: solarDay.getDay()
          }, // 公历日期
          lunar: {
            year: lunarDay.getYear(),
            month: lunarDay.getMonth(),
            day: lunarDay.getDay(),
            dayName: lunarDay.getName() // 阴历日期名称，如"初一"、"十五"等
          } // 阴历日期
        },
        monthSixtyCycle: selectedMonth.ganzhi, // 所属流月干支
      }));
      
      currentDay = currentDay.next(1);
      dayCount++;
    }
    
    return result;
  } catch (error) {
    handleError(error, 'getDayList');
  }
}

/**
 * 获取流时列表
 * @param childLimit ChildLimit对象
 * @param decadeIndex 大运索引
 * @param fortuneIndex 流年索引
 * @param monthIndex 流月索引
 * @param dayIndex 流日索引
 * @returns 流时列表
 */
export function getHourList(childLimit: ChildLimit, decadeIndex: number, fortuneIndex: number, monthIndex: number, dayIndex: number) {
  try {
    const result: any = [];
    
    // 从 childLimit 内部获取日干（日元）
    const dayMaster = childLimit.getEightChar().getDay().getHeavenStem();
    
    // 获取指定流日信息
    const dayList = getDayList(childLimit, decadeIndex, fortuneIndex, monthIndex);
    if (!dayList || dayList.length === 0) {
      handleError(new Error('dayList is empty'), 'getHourList');
    }
    if (dayIndex >= dayList.length) {
      handleError(new Error('dayIndex out of range'), 'getHourList');
    }
    const selectedDay = dayList[dayIndex]; // dayIndex 从0开始，直接使用
    
    // 获取指定年份、月份的干支年月对象
    const fortuneInfo = getFortuneList(childLimit, decadeIndex);
    const actualDisplayYear = fortuneInfo[fortuneIndex].year;
    const realYear = SixtyCycleYear.fromYear(actualDisplayYear);
    const months = realYear.getMonths();
    const targetMonth = months[monthIndex];
    
    // 从流月的第一天开始，找到指定的日子
    const firstDay = targetMonth.getFirstDay();
    let targetDay = firstDay;
    for (let i = 0; i < dayIndex; i++) { // dayIndex 从0开始，所以从0开始循环
      targetDay = targetDay.next(1);
    }
    
    // 获取该日的所有时辰（12个时辰）
    const solarDay = targetDay.getSolarDay();
    const lunarDay = solarDay.getLunarDay();
    const hours = lunarDay.getHours();
    
    // 传统十二时辰的时间范围
    const timeRanges = [
      { start: 23, end: 1 },   // 子时 23:00-01:00
      { start: 1, end: 3 },    // 丑时 01:00-03:00
      { start: 3, end: 5 },    // 寅时 03:00-05:00
      { start: 5, end: 7 },    // 卯时 05:00-07:00
      { start: 7, end: 9 },    // 辰时 07:00-09:00
      { start: 9, end: 11 },   // 巳时 09:00-11:00
      { start: 11, end: 13 },  // 午时 11:00-13:00
      { start: 13, end: 15 },  // 未时 13:00-15:00
      { start: 15, end: 17 },  // 申时 15:00-17:00
      { start: 17, end: 19 },  // 酉时 17:00-19:00
      { start: 19, end: 21 },  // 戌时 19:00-21:00
      { start: 21, end: 23 }   // 亥时 21:00-23:00
    ];
    
    // 只处理前12个时辰（传统上一天只有12个时辰）
    const hourCount = Math.min(hours.length, 12);
    
    for (let i = 0; i < hourCount; i++) {
      const hour = hours[i];
      
      // 获取流时的天干地支用于计算十神
      const hourSixtyCycle = hour.getSixtyCycle();
      
      // 使用通用方法计算详细信息
      const info = calculateSixtyCycleInfo(childLimit, dayMaster, hourSixtyCycle);
      
      result.push(buildCommonResultObject(hour.getSixtyCycle().getName(), info, {
        hourIndex: i, // 时辰序号（0-11）
        hourName: hour.getName(), // 时辰名称，如"子时"、"丑时"
        timeRange: timeRanges[i], // 传统时辰时间范围
        daySixtyCycle: selectedDay.ganzhi, // 所属流日干支
        date: selectedDay.date, // 日期信息（包含solar和lunar）
      }));
    }
    
    return result;
  } catch (error) {
    handleError(error, 'getHourList');
  }
}

/**
 * 创建八字对象 - 从 service 移过来
 * @param solarTime 阳历时间
 * @param gender 性别
 * @returns ChildLimit对象
 */
export function createChildLimit(solarTime: SolarTime, gender: Gender, enableZiShiSupport: boolean = true): ChildLimit {
  try {
    return ChildLimit.fromSolarTime(solarTime, gender, enableZiShiSupport);
  } catch (error) {
    handleError(error, 'createChildLimit');
    // 这行永远不会执行，因为 handleError 会抛出异常
    throw error;
  }
}

/**
 * 获取出生日期的节气信息（基于12个月份的开始节气）
 * @param solarTime 阳历时间
 * @returns 节气信息对象
 */
export function getBirthdaySolarTermInfo(solarTime: SolarTime) {
  const solarDay = solarTime.getSolarDay();
  const birthYear = solarDay.getYear();
  
  // 12个节气对应的索引（每个月开始时的节气）
  const monthToTermIndex: Record<number, number> = {
    1: 3,   // 正月：立春 (索引3)
    2: 5,   // 二月：惊蛰 (索引5)
    3: 7,   // 三月：清明 (索引7)
    4: 9,   // 四月：立夏 (索引9)
    5: 11,  // 五月：芒种 (索引11)
    6: 13,  // 六月：小暑 (索引13)
    7: 15,  // 七月：立秋 (索引15)
    8: 17,  // 八月：白露 (索引17)
    9: 19,  // 九月：寒露 (索引19)
    10: 21, // 十月：立冬 (索引21)
    11: 23, // 十一月：大雪 (索引23)
    12: 1   // 十二月：小寒 (索引1)
  };
  
  // 获取出生年份前后两年的所有12个节气，确保覆盖所有可能的跨年情况
  const allTerms: Array<{index: number, name: string, time: SolarTime, year: number, month: number}> = [];
  
  // 获取前一年、当年、后一年的所有12个节气
  for (let year = birthYear - 1; year <= birthYear + 1; year++) {
    for (let month = 1; month <= 12; month++) {
      const termIndex = monthToTermIndex[month];
      let termYear = year;
      
      // 处理跨年情况
      if (month === 12) {
        // 十二月的小寒可能在下一年的1月
        try {
          const term = SolarTerm.fromIndex(year, termIndex);
          const termTime = term.getJulianDay().getSolarTime();
          if (termTime.getSolarDay().getYear() > year) {
            // 如果小寒在下一年的1月，使用下一年的节气
            termYear = year + 1;
          }
        } catch (error) {
          // 如果获取失败，尝试下一年的节气
          termYear = year + 1;
        }
      }
      
      try {
        const term = SolarTerm.fromIndex(termYear, termIndex);
        const termTime = term.getJulianDay().getSolarTime();
        allTerms.push({
          index: termIndex,
          name: term.getName(),
          time: termTime,
          year: termYear,
          month: month
        });
      } catch (error) {
        // 忽略无法获取的节气，继续处理下一个
        continue;
      }
    }
  }
  
  // 按时间顺序排序节气
  allTerms.sort((a, b) => a.time.subtract(b.time));
  
  // 找到出生时间前后的两个节气
  let beforeTerm: {index: number, name: string, time: SolarTime, year: number, month: number} | null = null;
  let afterTerm: {index: number, name: string, time: SolarTime, year: number, month: number} | null = null;
  
  for (let i = 0; i < allTerms.length; i++) {
    const term = allTerms[i];
    if (solarTime.subtract(term.time) >= 0) {
      // 出生时间在节气之后或等于
      beforeTerm = term;
    } else {
      // 出生时间在节气之前
      afterTerm = term;
      break;
    }
  }
  
  // 如果没有找到前一个节气，说明出生时间在年初，使用上一年的最后一个节气
  if (!beforeTerm) {
    // 找到前一年最后一个节气（小寒）
    const lastYearTerms = allTerms.filter(term => term.year === birthYear - 1);
    if (lastYearTerms.length > 0) {
      beforeTerm = lastYearTerms[lastYearTerms.length - 1];
    } else {
      // 如果找不到，尝试直接获取前一年的小寒
      try {
        const lastYearTerm = SolarTerm.fromIndex(birthYear - 1, 1); // 小寒是索引1
        beforeTerm = {
          index: 1,
          name: lastYearTerm.getName(),
          time: lastYearTerm.getJulianDay().getSolarTime(),
          year: birthYear - 1,
          month: 12
        };
      } catch (error) {
        throw new Error('无法找到出生日期的前一个节气');
      }
    }
  }
  
  // 如果没有找到后一个节气，说明出生时间在年末，使用下一年的第一个节气
  if (!afterTerm) {
    // 找到下一年第一个节气（立春）
    const nextYearTerms = allTerms.filter(term => term.year === birthYear + 1);
    if (nextYearTerms.length > 0) {
      afterTerm = nextYearTerms[0];
    } else {
      // 如果找不到，尝试直接获取下一年的立春
      try {
        const nextYearTerm = SolarTerm.fromIndex(birthYear + 1, 3); // 立春是索引3
        afterTerm = {
          index: 3,
          name: nextYearTerm.getName(),
          time: nextYearTerm.getJulianDay().getSolarTime(),
          year: birthYear + 1,
          month: 1
        };
      } catch (error) {
        throw new Error('无法找到出生日期的后一个节气');
      }
    }
  }
  
  // 确保找到了前后节气
  if (!beforeTerm || !afterTerm) {
    throw new Error('无法找到出生日期的前后节气');
  }
  
  // 计算时间差
  const secondsAfterBefore = solarTime.subtract(beforeTerm.time);
  const secondsBeforeAfter = afterTerm.time.subtract(solarTime);
  
  // 转换为天和小时
  const daysAfterBefore = Math.floor(secondsAfterBefore / 86400);
  const hoursAfterBefore = Math.floor((secondsAfterBefore % 86400) / 3600);
  const daysBeforeAfter = Math.floor(secondsBeforeAfter / 86400);
  const hoursBeforeAfter = Math.floor((secondsBeforeAfter % 86400) / 3600);
  
  // 格式化时间
  const formatTime = (time: SolarTime) => {
    return `${time.getSolarDay().getYear()}-${time.getSolarDay().getMonth().toString().padStart(2, '0')}-${time.getSolarDay().getDay().toString().padStart(2, '0')} ${time.getHour().toString().padStart(2, '0')}:${time.getMinute().toString().padStart(2, '0')}:${time.getSecond().toString().padStart(2, '0')}`;
  };
  
  const formatDescription = `出生于${beforeTerm.name}后${daysAfterBefore}天${hoursAfterBefore}小时，${afterTerm.name}前${daysBeforeAfter}天${hoursBeforeAfter}小时`;
  
  return {
    start: {
      jieqi: beforeTerm.name,
      time: formatTime(beforeTerm.time)
    },
    end: {
      jieqi: afterTerm.name,
      time: formatTime(afterTerm.time)
    },
    format: formatDescription
  };
}

/**
 * 获取基本信息
 * @param solarTime 阳历时间
 * @param gender 性别
 * @param childLimit 童限对象
 * @param dayMaster 日干
 * @param dayInfo 日柱信息
 * @param shengong 身宫信息
 * @param minggong 命宫信息
 * @param taiyuan 胎元信息
 * @param taixi 胎息信息
 * @param name 姓名（可选）
 * @param longitude 经度（可选，用于计算真太阳时）
 * @param latitude 纬度（可选，用于计算真太阳时）
 * @returns 基本信息对象
 */
export function getBaseInfo(
  solarTime: SolarTime,
  gender: Gender,
  childLimit: ChildLimit,
  dayMaster: HeavenStem,
  dayInfo: any,
  shengong: any,
  minggong: any,
  taiyuan: any,
  taixi: any,
  name?: string,
  longitude?: number,
  latitude?: number,
  enableZiShiSupport: boolean = true
) {
  const solarDay = solarTime.getSolarDay();
  const lunarDay = solarDay.getLunarDay();
  const eightChar = childLimit.getEightChar();
  const yearPillar = eightChar.getYear();

  // 获取生肖和星座
  const zodiac = yearPillar.getEarthBranch().getZodiac().getName();
  const constellation = solarDay.getConstellation().getName();
  
  // 获取农历信息 - 根据配置选择Provider
  const lunarHour = solarTime.getLunarHour(enableZiShiSupport);
  const lunarMonth = lunarDay.getLunarMonth();
  
  const lunarMonthName = lunarMonth.getName();
  const lunarDayName = lunarDay.getName();
  const hourName = lunarHour.getSixtyCycle().getEarthBranch().getName() + '时';
  
  // 获取节气信息
  const birthdayJieqi = getBirthdaySolarTermInfo(solarTime);

  // 获取人元司令分野
  const hideHeavenStemDay = solarDay.getHideHeavenStemDay();
  const humanYuanCommander = hideHeavenStemDay.getName() + '用事';
  
  // 获取星宿信息
  const twentyEightStar = lunarDay.getTwentyEightStar();
  const sevenStar = twentyEightStar.getSevenStar();
  const zone = twentyEightStar.getZone();
  const beast = zone.getBeast();
  const starMansion = twentyEightStar.getName() + '宿' + zone.getName() + '方' + beast.getName();
  
  // 计算命卦（基于出生年份）
  const lifeHexagram = calculateMinggua(solarDay.getYear(), gender);

  // 计算真太阳时（如果有经纬度信息）
  let trueSolarTime = `${solarDay.getYear()}年${solarDay.getMonth().toString().padStart(2, '0')}月${solarDay.getDay().toString().padStart(2, '0')}日 ${solarTime.getHour().toString().padStart(2, '0')}:${solarTime.getMinute().toString().padStart(2, '0')}`;
  if (longitude !== undefined && latitude !== undefined) {
    // TODO: 后续实现真太阳时计算逻辑
    // 这里可以根据经纬度计算时差，然后调整时间
    trueSolarTime = `${solarDay.getYear()}年${solarDay.getMonth().toString().padStart(2, '0')}月${solarDay.getDay().toString().padStart(2, '0')}日 ${solarTime.getHour().toString().padStart(2, '0')}:${solarTime.getMinute().toString().padStart(2, '0')} (真太阳时)`;
  }

  // 构建出生地区信息
  let birthLocation = '未知地 北京时间 --';
  if (longitude !== undefined && latitude !== undefined) {
    birthLocation = `经度: ${longitude}° 纬度: ${latitude}°`;
  }

  return {
    // 基本信息
    name: name || '', // 姓名 - 使用传入参数或默认为空
    gender: gender === Gender.MAN ? '男' : '女',
    genderTraditional: gender === Gender.MAN ? '乾造' : '坤造',
    
    // 日期信息
    nongli: `${lunarDay.getYear()}年${lunarMonthName}${lunarDayName} ${hourName}`, // 农历
    yangli: `${solarDay.getYear()}年${solarDay.getMonth().toString().padStart(2, '0')}月${solarDay.getDay().toString().padStart(2, '0')}日 ${solarTime.getHour().toString().padStart(2, '0')}:${solarTime.getMinute().toString().padStart(2, '0')}`, // 阳历
    shengxiao: zodiac, // 生肖
    constellation: constellation, // 星座
    zhenTaiyangshi: trueSolarTime, // 真太阳时
    
    // 地区信息
    chushengdiqu: birthLocation, // 出生地区
    
    // 节气信息
    birthdayJieqi: birthdayJieqi, // 出生节气信息
    
    // 星宿信息
    xingxiu: starMansion, // 星宿
    
    // 胎息胎元
    taixi: taixi.ganzhi + ' (' + taixi.nayin + ')', // 胎息
    taiyuan: taiyuan.ganzhi + ' (' + taiyuan.nayin + ')', // 胎元
    
    // 人元司令分野
    renyuansilingfenye: humanYuanCommander, // 人元司令分野
    
    // 空亡
    kongwang: dayInfo.kongwang, // 空亡
    
    // 身宫命宫
    shengong: shengong.ganzhi + ' (' + shengong.nayin + ')', // 身宫
    minggong: minggong.ganzhi + ' (' + minggong.nayin + ')', // 命宫
    
    // 命卦
    minggua: lifeHexagram // 命卦
  };
}

/**
 * 获取完整八字信息 - 核心方法，所有逻辑完全内联
 * @param solarTime 阳历时间
 * @param gender 性别
 * @param name 姓名（可选）
 * @param longitude 经度（可选，用于计算真太阳时）
 * @param latitude 纬度（可选，用于计算真太阳时）
 * @param enableZiShiSupport 是否启用早晚子时支持（可选，默认true）
 * @returns 完整八字信息
 */
export function getFullBaziInfo(solarTime: SolarTime, gender: Gender, name?: string, longitude?: number, latitude?: number, enableZiShiSupport: boolean = true) {
  try {
    const childLimit = ChildLimit.fromSolarTime(solarTime, gender, enableZiShiSupport);
    const eightChar = childLimit.getEightChar();
    
    // 获取四柱信息
    const yearPillar = eightChar.getYear();
    const monthPillar = eightChar.getMonth();
    const dayPillar = eightChar.getDay();
    const hourPillar = eightChar.getHour();
    
    // 获取日干（用于计算十神）
    const dayMaster = dayPillar.getHeavenStem();
    
    // 格式化日期
    const solarDay = solarTime.getSolarDay();
    const lunarDay = solarDay.getLunarDay();
    
    // 计算各柱详细信息 - 完全内联，不调用任何私有方法
    const yearInfo = calculateSpecialPillarInfo(childLimit, dayMaster, yearPillar);
    const monthInfo = calculateSpecialPillarInfo(childLimit, dayMaster, monthPillar);
    const dayInfo = calculateSpecialPillarInfo(childLimit, dayMaster, dayPillar);
    const hourInfo = calculateSpecialPillarInfo(childLimit, dayMaster, hourPillar);
    
    // 只有日柱需要特殊处理十神
    dayInfo.tenStar = '元' + (gender === Gender.MAN ? '男' : '女');
    
    // 为各柱添加神煞信息
    try {
      yearInfo.shenshas = calculatePillarShensha(childLimit, 'year');
    } catch (error) {
      yearInfo.shenshas = [];
    }
    
    try {
      monthInfo.shenshas = calculatePillarShensha(childLimit, 'month');
    } catch (error) {
      monthInfo.shenshas = [];
    }
    
    try {
      dayInfo.shenshas = calculatePillarShensha(childLimit, 'day');
    } catch (error) {
      dayInfo.shenshas = [];
    }
    
    try {
      hourInfo.shenshas = calculatePillarShensha(childLimit, 'hour');
    } catch (error) {
      hourInfo.shenshas = [];
    }
    
    // 计算身宫、命宫、胎元、胎息
    const shengong = calculateSpecialPillarInfo(childLimit, dayMaster, eightChar.getBodySign());
    const minggong = calculateSpecialPillarInfo(childLimit, dayMaster, eightChar.getOwnSign());
    const taiyuan = calculateSpecialPillarInfo(childLimit, dayMaster, eightChar.getFetalOrigin());
    const taixi = calculateSpecialPillarInfo(childLimit, dayMaster, eightChar.getFetalBreath());

    // 获取基本信息
    const baseInfo = getBaseInfo(solarTime, gender, childLimit, dayMaster, dayInfo, shengong, minggong, taiyuan, taixi, name, longitude, latitude, enableZiShiSupport);

    // 计算五行个数统计
    const wuxing = calculateSimpleWuxingCount(eightChar);

    return {
      title: '四柱八字',
      baseInfo,
      year: yearInfo,
      month: monthInfo,
      day: dayInfo,
      hour: hourInfo,
      shengong: shengong,
      minggong: minggong,
      taiyuan: taiyuan,
      wuxing: wuxing
    };
  } catch (error) {
    handleError(error, 'getFullBaziInfo');
  }
}
